{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0484b0d1",
   "metadata": {},
   "source": [
    "# Test transforms\n",
    "\n",
    "We need transforms to change the input to the sentiment model and the output from the sentiment model to allow for easier integration with the Alibi Explain explainer. The input to the explainer will come from the output of the speech recognition model which returns a Dict so we extract the text and turn into a simple list. Similarly, the sentiment model returns a Dict so we convert to a simple binary classifer result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "89e723ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e529edd",
   "metadata": {},
   "source": [
    "## Sentiment Input Transform\n",
    "\n",
    "run `mlserver start .` from the `sentiment-input-transform` folder.\n",
    "\n",
    "This code turns the Dict into a simple list of strings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d42e1952",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'model_name': 'sentiment',\n",
       " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
       " 'parameters': {'content_type': 'str'},\n",
       " 'outputs': [{'name': 'output-1',\n",
       "   'shape': [1, 1],\n",
       "   'datatype': 'BYTES',\n",
       "   'parameters': {'content_type': 'str'},\n",
       "   'data': ['This is not amazing at all.']}]}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inference_request = {\n",
    "    \"inputs\": [\n",
    "        {\n",
    "          \"name\": \"predict\",\n",
    "          \"shape\": [1],\n",
    "          \"datatype\": \"BYTES\",\n",
    "          \"data\": ['{\"text\": \"This is not amazing at all.\"}'],\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "requests.post(\"http://localhost:8080/v2/models/sentiment-input-transform_1/infer\", json=inference_request).json()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62cb89d8",
   "metadata": {},
   "source": [
    "## Sentiment Output Transform\n",
    "\n",
    "run `mlserver start .` from the `sentiment-output-transform` folder.\n",
    "\n",
    "This code turns the Dict result from the sentiment model and returns a simple 1 or 0 classifier prediction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "62546736",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'model_name': 'sentiments',\n",
       " 'id': '2a4eeab2-c19b-4455-8c2c-2ab68b429ec9',\n",
       " 'parameters': {'content_type': 'np'},\n",
       " 'outputs': [{'name': 'output-1',\n",
       "   'shape': [2, 1],\n",
       "   'datatype': 'INT64',\n",
       "   'parameters': {'content_type': 'np'},\n",
       "   'data': [1, 0]}]}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inference_request = {\n",
    "    \"inputs\": [\n",
    "        {\n",
    "          \"name\": \"predict\",\n",
    "          \"shape\": [1],\n",
    "          \"datatype\": \"BYTES\",\n",
    "          \"data\": ['{\"label\": \"POSITIVE\", \"score\":\"0.99\"}','{\"label\": \"NEGATIVE\", \"score\":\"0.99\"}'],\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "requests.post(\"http://localhost:8080/v2/models/sentiment-output-transform_1/infer\", json=inference_request).json()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67a6a864",
   "metadata": {},
   "source": [
    "## Sentiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "ec48708f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'model_name': 'sentiment_1',\n",
       " 'model_version': '1',\n",
       " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
       " 'parameters': {},\n",
       " 'outputs': [{'name': 'output',\n",
       "   'shape': [1, 1],\n",
       "   'datatype': 'BYTES',\n",
       "   'parameters': {'content_type': 'hg_jsonlist'},\n",
       "   'data': ['{\"label\": \"NEGATIVE\", \"score\": 0.9997649788856506}']}]}"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inference_request = {'model_name': 'sentiment',\n",
    " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
    " 'parameters': {'content_type': 'hf'},\n",
    " 'inputs': [{'name': 'args',\n",
    "   'shape': [1, 1],\n",
    "   'datatype': 'BYTES',\n",
    "   'parameters': {'content_type': 'hf'},\n",
    "   'data': ['This is not amazing at all.']}]}\n",
    "\n",
    "requests.post(\"http://localhost:8080/v2/models/sentiment_1/infer\", json=inference_request).json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "154027a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'model_name': 'sentiment_1',\n",
       " 'model_version': '1',\n",
       " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
       " 'parameters': {},\n",
       " 'outputs': [{'name': 'output',\n",
       "   'shape': [1, 1],\n",
       "   'datatype': 'BYTES',\n",
       "   'parameters': {'content_type': 'hg_jsonlist'},\n",
       "   'data': ['{\"label\": \"NEGATIVE\", \"score\": 0.9997649788856506}']}]}"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inference_request = {'model_name': 'sentiment',\n",
    " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
    " 'inputs': [{'name': 'args',\n",
    "   'shape': [1, 1],\n",
    "   'datatype': 'BYTES',\n",
    "   'parameters': {'content_type': 'str'},\n",
    "   'data': ['This is not amazing at all.']}]}\n",
    "\n",
    "requests.post(\"http://localhost:8080/v2/models/sentiment_1/infer\", json=inference_request).json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "6a5d3925",
   "metadata": {},
   "outputs": [
    {
     "ename": "JSONDecodeError",
     "evalue": "Expecting value: line 1 column 1 (char 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mJSONDecodeError\u001b[0m                           Traceback (most recent call last)",
      "File \u001b[0;32m~/miniconda3/envs/scv2/lib/python3.9/site-packages/requests/models.py:971\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m    970\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 971\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcomplexjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    972\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m JSONDecodeError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    973\u001b[0m     \u001b[38;5;66;03m# Catch JSON-related errors and raise as requests.JSONDecodeError\u001b[39;00m\n\u001b[1;32m    974\u001b[0m     \u001b[38;5;66;03m# This aliases json.JSONDecodeError and simplejson.JSONDecodeError\u001b[39;00m\n",
      "File \u001b[0;32m~/miniconda3/envs/scv2/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m    343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m    344\u001b[0m         parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m    345\u001b[0m         parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "File \u001b[0;32m~/miniconda3/envs/scv2/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m    333\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m    334\u001b[0m \u001b[38;5;124;03mcontaining a JSON document).\u001b[39;00m\n\u001b[1;32m    335\u001b[0m \n\u001b[1;32m    336\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n",
      "File \u001b[0;32m~/miniconda3/envs/scv2/lib/python3.9/json/decoder.py:355\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m    354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 355\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m JSONDecodeError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpecting value\u001b[39m\u001b[38;5;124m\"\u001b[39m, s, err\u001b[38;5;241m.\u001b[39mvalue) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m    356\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m obj, end\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m                           Traceback (most recent call last)",
      "Input \u001b[0;32mIn [36]\u001b[0m, in \u001b[0;36m<cell line: 10>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m inference_request \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmodel_name\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124msentiment\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m      2\u001b[0m  \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mid\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124md49609fb-d950-439c-b06f-3c455f03a2b4\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m      3\u001b[0m                      \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mparameters\u001b[39m\u001b[38;5;124m'\u001b[39m: {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcontent_type\u001b[39m\u001b[38;5;124m\"\u001b[39m:\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstr\u001b[39m\u001b[38;5;124m\"\u001b[39m},\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m      7\u001b[0m    \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mparameters\u001b[39m\u001b[38;5;124m'\u001b[39m: {\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcontent_type\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mstr\u001b[39m\u001b[38;5;124m'\u001b[39m},\n\u001b[1;32m      8\u001b[0m    \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdata\u001b[39m\u001b[38;5;124m'\u001b[39m: [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mThis is not amazing at all.\u001b[39m\u001b[38;5;124m'\u001b[39m]}]}\n\u001b[0;32m---> 10\u001b[0m \u001b[43mrequests\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpost\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mhttp://localhost:8080/v2/models/sentiment_1/infer\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mjson\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minference_request\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/miniconda3/envs/scv2/lib/python3.9/site-packages/requests/models.py:975\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m    971\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m complexjson\u001b[38;5;241m.\u001b[39mloads(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtext, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m    972\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m JSONDecodeError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    973\u001b[0m     \u001b[38;5;66;03m# Catch JSON-related errors and raise as requests.JSONDecodeError\u001b[39;00m\n\u001b[1;32m    974\u001b[0m     \u001b[38;5;66;03m# This aliases json.JSONDecodeError and simplejson.JSONDecodeError\u001b[39;00m\n\u001b[0;32m--> 975\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m RequestsJSONDecodeError(e\u001b[38;5;241m.\u001b[39mmsg, e\u001b[38;5;241m.\u001b[39mdoc, e\u001b[38;5;241m.\u001b[39mpos)\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)"
     ]
    }
   ],
   "source": [
    "inference_request = {'model_name': 'sentiment',\n",
    " 'id': 'd49609fb-d950-439c-b06f-3c455f03a2b4',\n",
    "                     'parameters': {\"content_type\":\"str\"},\n",
    " 'inputs': [{'name': 'args',\n",
    "   'shape': [1, 1],\n",
    "   'datatype': 'BYTES',\n",
    "   'parameters': {'content_type': 'str'},\n",
    "   'data': ['This is not amazing at all.']}]}\n",
    "\n",
    "requests.post(\"http://localhost:8080/v2/models/sentiment_1/infer\", json=inference_request).json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "894422c3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'sentiment_1',\n",
       " 'versions': [],\n",
       " 'platform': '',\n",
       " 'inputs': [{'name': 'args', 'datatype': 'BYTES', 'shape': [1]},\n",
       "  {'name': 'args',\n",
       "   'datatype': 'BYTES',\n",
       "   'shape': [-1],\n",
       "   'parameters': {'content_type': 'hf'}}],\n",
       " 'outputs': [{'name': 'outputs',\n",
       "   'datatype': 'BYTES',\n",
       "   'shape': [-1],\n",
       "   'parameters': {'content_type': 'hg_json'}}],\n",
       " 'parameters': {}}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "requests.get(\"http://localhost:8080/v2/models/sentiment_1\").json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97e37a91",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
